Skip to content

[Feature/#114] 루틴 리스트 화면 미구현 기능을 구현합니다.#115

Merged
wjdrjs00 merged 5 commits intodevelopfrom
feature/#114-routine-list
Aug 20, 2025
Merged

[Feature/#114] 루틴 리스트 화면 미구현 기능을 구현합니다.#115
wjdrjs00 merged 5 commits intodevelopfrom
feature/#114-routine-list

Conversation

@wjdrjs00
Copy link
Copy Markdown
Member

@wjdrjs00 wjdrjs00 commented Aug 19, 2025

[ PR Content ]

루틴 리스트 화면 미구현 기능을 구현했습니다.

Related issue

Screenshot 📸

Screen_recording_20250820_021843.mp4

Work Description

  • 루틴 기간 ui 추가
  • 삭제된 루틴의 경우 "수정" 불가능 로직 추가
  • 삭제 성공 시 로직 추가(루틴 조회 api 호출, 토스트 메시지 제공)
  • 토스트 메시지 디자인 수정

To Reviewers 📢

  • 기존에 루틴리스트 화면에 미구현 되어있던 기능들을 구현했습니다.
  • 수정하기 성공 시 토스트 메시지를 띄워주는 로직은 토스트메시지가 전역으로 구현되어 있기 때문에, 수정하기 화면에서 호출하는 방식으로 구현하는것도 크게 문제가 되지 않을것이라 생각하여 해당 작업에서는 구현하지 않았습니다!
  • 추가로 이전 v1에서는 삭제하기를 낙관적 방식으로 구현했지만, v2로 변경됨에따라 아래와 같은 이유로 낙관적 업데이트 방식을 지원하지 않았습니다.
    • 이유:
      v2로 넘어오면서 기회측에서 삭제되어도 이전 기록을 남겨달라는 요구사항이 있었습니다.
      이에 따라 서버에서 삭제에 대한 기준이 "오늘"을 기점으로 이전 날에 대한 기록은 삭제가 되어도 여전히 리스트에서 보여짐(단, 수정하기 버튼이 사라짐),
      오늘을 기점으로 이후 날들은 삭제시 영구히 사라져서 리스트에 더 이상 표기되지 않음.
      따라서, 이런 케이스를 모두 고려하여 낙관적 업데이트 구현하기에 리소스 부족과, 기획이 수정될 가능성이 높다 판단하여 비관적 방식으로 구현했습니다.
  • 이외 궁굼하신점 리뷰 남겨주세욤~!

Summary by CodeRabbit

  • New Features
    • 루틴 삭제 완료 시 확인 토스트가 표시됩니다.
    • 루틴 상세에 기간이 짧은 날짜 형식(yy.MM.dd)으로 표시되며, 삭제된 루틴은 편집 버튼이 숨겨집니다.
    • 반복 요일이 없을 때 표기가 “x”로 변경되었습니다.
    • 홈 화면에서 루틴 토글 실패 토스트 표시가 제거되었습니다.
  • Style
    • 토스트가 시스템 내비게이션 영역을 반영하고 디자인이 개선되었습니다(레이아웃·아이콘 업데이트).
    • 경고 아이콘 그래픽이 업데이트되었습니다.
    • 루틴 상세 텍스트 스타일이 정리되었습니다.

- 삭제된 루틴일경우 수정버튼 제거
- 기간 표시
- 텍스트 간격 조정
- 홈에서 제공하던 토스트메시지 제거
- 바텀네비게이션바를 가진 화면과 아닌화면 패딩 구분
@wjdrjs00 wjdrjs00 requested a review from l5x5l August 19, 2025 17:31
@wjdrjs00 wjdrjs00 self-assigned this Aug 19, 2025
@wjdrjs00 wjdrjs00 added ✨ Feature 새로운 기능 구현 🧤 대현 labels Aug 19, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Aug 19, 2025

Walkthrough

전체적으로 토스트 컴포넌트의 API/레이아웃을 변경하고, 글로벌 토스트 호출 시그니처를 갱신했습니다. 루틴 리스트 화면에 기간 표시/삭제 완료 처리/리스트 갱신과 토스트 사이드이펙트를 추가했습니다. 홈 화면의 토스트 관련 사이드이펙트는 제거되었고, 내비게이션/인셋 처리와 경고 아이콘, 요일 포맷 일부가 수정되었습니다.

Changes

Cohort / File(s) Change Summary
Toast 시스템 API/레이아웃 갱신
core/designsystem/.../BitnagilToastMessage.kt, presentation/.../common/toast/GlobalBitnagilToast.kt
토스트 메시지 컴포저블을 Row 기반, 새 배경/라운드/간격으로 변경하고 아이콘을 필수 파라미터(Int)로 변경. BitnagilToastState와 show 시그니처를 Int로 통일. GlobalBitnagilToast.show도 아이콘 필수 및 체크 아이콘 리소스 교체.
루틴 리스트 기능 추가/갱신
presentation/.../routinelist/RoutineListScreen.kt, presentation/.../routinelist/RoutineListViewModel.kt, presentation/.../routinelist/model/RoutineListIntent.kt, presentation/.../routinelist/model/RoutineListSideEffect.kt, presentation/.../routinelist/model/RoutineUiModel.kt, presentation/.../routinelist/component/template/RoutineDetailsCard.kt, presentation/.../home/util/LocalDateExtension.kt
삭제 성공 흐름(OnSuccessDeletedRoutine) 추가, 리스트 재조회(fetchRoutines) 후 토스트 사이드이펙트 발행. RoutineListSideEffect.ShowToast 추가 및 화면에서 GlobalBitnagilToast.showCheck 처리. RoutineUiModel에 startDate/endDate/routineDeletedYn 추가와 formattedDateRange 제공. 카드 UI에 기간 표시와 편집 버튼 조건 노출. 날짜 짧은 포맷 확장 추가.
홈 화면 사이드이펙트 정리
presentation/.../home/HomeScreen.kt, presentation/.../home/HomeViewModel.kt, presentation/.../home/model/HomeSideEffect.kt
홈 화면의 토스트 관련 사이드이펙트 타입(ShowToast, ShowToastWithIcon) 제거 및 호출 코드 삭제. 실패 토글 시 토스트 발행 제거.
네비/인셋 처리
app/src/main/java/.../MainActivity.kt, app/src/main/java/.../MainNavigator.kt
토스트 컨테이너에 navigationBarsPadding 적용 및 하단 바 유무에 따른 조건부 하단 패딩. MainNavigator에 현재 목적지 파생 및 hasBottomNavigationBarRoute 추가.
디자인 에셋 수정
core/designsystem/src/main/res/drawable/ic_warning.xml
경고 아이콘 벡터 경로 재작성: 핑크 아웃라인 + 화이트 스트로크/도트 디테일 추가.
도메인 포맷 변경
domain/.../DayOfWeek.kt
비어있는 반복일 포맷 반환값을 "반복 없음"에서 "x"로 변경.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as 사용자
  participant UI as RoutineListScreen
  participant VM as RoutineListViewModel
  participant Repo as RoutineRepository
  participant Toast as GlobalBitnagilToast

  User->>UI: 루틴 삭제 확인
  UI->>VM: deleteRoutine(intent)
  VM->>Repo: deleteRoutine(...)
  Repo-->>VM: 성공
  VM->>VM: fetchRoutines()
  VM->>UI: SideEffect.ShowToast("삭제가 완료되었습니다.")
  UI->>Toast: showCheck(message)
Loading
sequenceDiagram
  autonumber
  participant Activity as MainActivity
  participant Navigator as MainNavigator
  participant System as System Insets

  Activity->>Navigator: hasBottomNavigationBarRoute()
  Navigator-->>Activity: Boolean
  Activity->>Activity: navigationBarsPadding 적용
  Activity->>Activity: bottom padding = 80dp (바 있음) / 16dp (없음)
  Note right of Activity: BitnagilToastContainer 배치 보정
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Assessment against linked issues

Objective Addressed Explanation
루틴 기간 UI 적용 (#114)
루틴 갱신로직 적용 (#114)
루틴 수정,삭제 토스트 메시지 구현 (#114) 삭제 토스트는 추가됨. 수정 토스트 구현 여부가 보이지 않음.

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
토스트 컨테이너 인셋/패딩 로직 변경 (app/src/main/java/com/threegap/bitnagil/MainActivity.kt) 루틴 리스트 기능 구현과 직접 관련 없음. 레이아웃 전역 보정.
내비게이터에 currentDestination/hasBottomNavigationBarRoute 추가 (app/src/main/java/com/threegap/bitnagil/MainNavigator.kt) 루틴 리스트 화면 기능 목표 외 전역 내비 구조 변경.
경고 아이콘 벡터 재디자인 (core/designsystem/src/main/res/drawable/ic_warning.xml) 이슈의 UI/기능 범위를 벗어난 디자인 자산 변경.
요일 포맷 빈 값 반환을 "x"로 변경 (domain/.../DayOfWeek.kt) 루틴 리스트 기간/갱신/토스트 요구사항과 무관한 도메인 텍스트 변경.
홈 화면 토스트 사이드이펙트 제거 (presentation/.../home/*) 루틴 리스트 화면 미구현 기능과 직접 관련되지 않음. 기능 축소/정리 성격.

Suggested reviewers

  • l5x5l

Poem

(/) ʕ•̀ω•́ʔゝ
오늘도 토스트가 사각— 딸칵— 띄워지네, 찰칵!
루틴은 삭제 후 새싹처럼 다시 갱신 싹싹.
날짜는 짧게, 경고는 반짝, 길도 반듯 인셋 착착.
깡총깡총 코드 밭, 토끼는 빌드에 박수 짝짝!
✅ 끝!

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/#114-routine-list

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (17)
domain/src/main/java/com/threegap/bitnagil/domain/routine/model/DayOfWeek.kt (1)

37-41: 매직 스트링 제거 및 API 유연성(기본 인자) 제안

"x"를 상수로 추출하고, 필요 시 UI에서 다른 심볼을 주입할 수 있도록 기본 인자를 제공하면 확장성과 가독성이 좋아집니다. 기존 호출부는 기본 인자 덕분에 변경 없이 동작합니다.

아래처럼 수정해 보세요:

-        fun List<DayOfWeek>.formatRepeatDays(): String {
-            if (this.isEmpty()) return "x"
+        private const val NO_REPEAT_SYMBOL: String = "x"
+
+        /**
+         * 요일 리스트를 "월, 화, ..." 형식의 문자열로 포맷합니다.
+         * 빈 리스트일 경우 [emptySymbol]을 반환합니다(기본값: "x").
+         */
+        fun List<DayOfWeek>.formatRepeatDays(emptySymbol: String = NO_REPEAT_SYMBOL): String {
+            if (this.isEmpty()) return emptySymbol
             return this.sortedBy { it.ordinal }
                 .joinToString(", ") { it.toKoreanShort() }
         }
app/src/main/java/com/threegap/bitnagil/MainNavigator.kt (2)

17-22: currentDestination 접근자는 @ReadOnlyComposable 부여 권장.

읽기 전용 Compose 상태만 참조하므로 의도를 명확히 하려면 @ReadOnlyComposable을 함께 부여하는 것을 권장합니다.

적용 예 (해당 범위 내 수정):

-    private val currentDestination: NavDestination?
-        @Composable get() {
+    private val currentDestination: NavDestination?
+        @Composable
+        @ReadOnlyComposable
+        get() {
             val currentEntry by navController.currentBackStackEntryAsState()
             return currentEntry?.destination
         }

파일 상단 import 추가(선택):

import androidx.compose.runtime.ReadOnlyComposable

30-37: 불필요한 when 사용을 단순화할 수 있습니다.

Boolean 반환에 when은 과합니다. 한 줄로 간결하게 표현 가능합니다.

간단화 diff:

-    internal fun hasBottomNavigationBarRoute(): Boolean {
-        val destination = currentDestination
-        return when {
-            destination?.hasRoute<Route.Home>() == true -> true
-            else -> false
-        }
-    }
+    internal fun hasBottomNavigationBarRoute(): Boolean {
+        val destination = currentDestination
+        return destination?.hasRoute<Route.Home>() == true
+    }

또한 향후 하단 바 대상이 늘어날 수 있다면 스케일 가능한 형태를 고려해 주세요(예: 여러 라우트 OR 매칭).

예시(참고용):

@Composable
internal fun hasBottomNavigationBarRoute(): Boolean {
    val destination = currentDestination ?: return false
    return destination.hasRoute<Route.Home>() ||
           destination.hasRoute<Route.Feed>() ||
           destination.hasRoute<Route.Profile>()
}
app/src/main/java/com/threegap/bitnagil/MainActivity.kt (1)

57-59: 토스트 컨테이너의 시스템 인셋 + 바텀 바 존재 조건 반영은 합리적입니다. 다만 매직 넘버는 상수화 권장.

.navigationBarsPadding()으로 시스템 바를 피하고, 라우트에 따라 바텀 여백을 조정한 접근은 👍. 80.dp/16.dp는 상수로 추출하여 의도를 드러내면 가독성과 유지보수성이 올라갑니다.

라인 내 변경 제안:

-                        .padding(bottom = if (mainNavigator.hasBottomNavigationBarRoute()) 80.dp else 16.dp),
+                        .padding(
+                            bottom = if (mainNavigator.hasBottomNavigationBarRoute())
+                                ToastBottomPaddingWithBottomBar
+                            else
+                                ToastBottomPaddingWithoutBottomBar
+                        ),

파일 내(클래스 바깥 또는 상단) 상수 정의 추가 예:

private val ToastBottomPaddingWithBottomBar = 80.dp
private val ToastBottomPaddingWithoutBottomBar = 16.dp

추가로, 라우트 전환 시 토스트 위치가 순간적으로 점프하는 게 거슬린다면 animateDpAsState로 부드럽게 보간하는 것도 고려해 볼 수 있습니다(선택).

core/designsystem/src/main/res/drawable/ic_warning.xml (2)

8-15: 중복 path를 단일 path로 병합하여 오버드로우와 유지보수 비용을 줄이세요

같은 pathData를 가진 두 개의 로 fill과 stroke를 나눠 그리는 대신, 단일 에서 fillColor와 stroke 속성을 함께 지정할 수 있습니다. 현재 구조는 오버드로우가 발생하고, 이후 geometry 변경 시 두 곳을 동기화해야 하는 유지보수 리스크가 있습니다.

아래와 같이 첫 번째 path에 stroke 속성을 추가하고, 두 번째 path(투명 fill + 동일 pathData + stroke)를 제거해 주세요.

-        android:pathData="M4.622,15.21C4.472,15.47 4.332,15.71 4.202,15.93C4.052,16.2 3.632,16.28 3.512,16.5C3.362,16.79 3.132,17 3.052,17.22C2.942,17.53 2.892,17.87 2.912,18.11C2.942,18.39 3.002,18.76 3.142,19C3.282,19.24 3.612,19.41 3.842,19.58C4.032,19.72 4.372,19.55 4.702,19.61C4.932,19.65 5.172,19.78 5.492,19.79C5.742,19.8 6.012,19.8 6.312,19.8C6.562,19.8 6.842,19.63 7.142,19.63C7.542,19.63 7.542,19.79 7.942,19.79C8.342,19.79 8.342,19.88 8.752,19.88C9.162,19.88 9.152,20.12 9.562,20.12C9.972,20.12 9.962,20.12 10.372,20.12C10.781,20.12 10.771,19.79 11.182,19.79C11.592,19.79 11.582,19.9 11.991,19.9C12.401,19.9 12.392,19.99 12.802,19.99C13.212,19.99 13.201,20.09 13.611,20.09C14.021,20.09 14.012,19.74 14.422,19.74C14.832,19.74 14.832,20.03 15.231,20.03C15.632,20.03 15.642,20.04 16.042,20.04C16.441,20.04 16.451,19.77 16.851,19.77C17.152,19.77 17.431,19.6 17.681,19.59C17.992,19.59 18.271,19.87 18.511,19.85C18.831,19.84 19.111,19.85 19.341,19.81C19.671,19.75 19.751,19.41 19.941,19.27C20.171,19.1 20.601,19.16 20.742,18.92C20.882,18.68 21.031,18.38 21.062,18.1C21.091,17.86 21.132,17.5 21.011,17.19C20.931,16.97 20.581,16.81 20.431,16.52C20.322,16.3 20.132,16.09 19.982,15.82C19.851,15.6 19.851,15.28 19.701,15.02C19.501,14.67 19.521,14.66 19.312,14.31C19.101,13.96 18.761,14.16 18.552,13.81C18.341,13.46 18.701,13.26 18.501,12.91C18.302,12.56 18.351,12.53 18.152,12.18C17.951,11.83 17.751,11.94 17.552,11.59C17.351,11.24 17.242,11.3 17.042,10.95C16.841,10.6 16.861,10.59 16.662,10.24C16.462,9.89 16.462,9.89 16.261,9.54C16.062,9.19 16.281,9.06 16.081,8.71C15.882,8.36 15.651,8.49 15.451,8.14C15.252,7.79 15.601,7.58 15.401,7.23C15.201,6.88 15.151,6.9 14.951,6.55C14.802,6.29 14.571,6.1 14.441,5.88C14.281,5.61 13.872,5.55 13.741,5.34C13.571,5.07 13.741,4.6 13.592,4.42C13.382,4.17 13.071,4.02 12.851,3.92C12.592,3.8 12.262,3.99 11.991,3.99C11.722,3.99 11.542,4.15 11.281,4.26C11.061,4.36 10.672,4.22 10.451,4.48C10.302,4.66 10.292,4.99 10.111,5.26C9.982,5.47 9.702,5.62 9.552,5.89C9.422,6.11 9.242,6.32 9.082,6.58C8.882,6.93 9.012,7 8.802,7.35C8.592,7.7 8.852,7.84 8.642,8.19C8.432,8.54 8.132,8.36 7.932,8.71C7.732,9.06 7.662,9.02 7.462,9.37C7.262,9.72 7.162,9.66 6.962,10.01C6.762,10.36 7.042,10.52 6.842,10.87C6.642,11.22 6.712,11.26 6.512,11.61C6.312,11.96 6.392,12.01 6.192,12.35C5.992,12.69 5.842,12.62 5.642,12.97C5.442,13.32 5.242,13.2 5.032,13.56C4.822,13.92 4.812,13.93 4.692,14.32C4.562,14.74 4.792,14.83 4.592,15.18L4.622,15.21Z" />
+        android:pathData="M4.622,15.21C4.472,15.47 4.332,15.71 4.202,15.93C4.052,16.2 3.632,16.28 3.512,16.5C3.362,16.79 3.132,17 3.052,17.22C2.942,17.53 2.892,17.87 2.912,18.11C2.942,18.39 3.002,18.76 3.142,19C3.282,19.24 3.612,19.41 3.842,19.58C4.032,19.72 4.372,19.55 4.702,19.61C4.932,19.65 5.172,19.78 5.492,19.79C5.742,19.8 6.012,19.8 6.312,19.8C6.562,19.8 6.842,19.63 7.142,19.63C7.542,19.63 7.542,19.79 7.942,19.79C8.342,19.79 8.342,19.88 8.752,19.88C9.162,19.88 9.152,20.12 9.562,20.12C9.972,20.12 9.962,20.12 10.372,20.12C10.781,20.12 10.771,19.79 11.182,19.79C11.592,19.79 11.582,19.9 11.991,19.9C12.401,19.9 12.392,19.99 12.802,19.99C13.212,19.99 13.201,20.09 13.611,20.09C14.021,20.09 14.012,19.74 14.422,19.74C14.832,19.74 14.832,20.03 15.231,20.03C15.632,20.03 15.642,20.04 16.042,20.04C16.441,20.04 16.451,19.77 16.851,19.77C17.152,19.77 17.431,19.6 17.681,19.59C17.992,19.59 18.271,19.87 18.511,19.85C18.831,19.84 19.111,19.85 19.341,19.81C19.671,19.75 19.751,19.41 19.941,19.27C20.171,19.1 20.601,19.16 20.742,18.92C20.882,18.68 21.031,18.38 21.062,18.1C21.091,17.86 21.132,17.5 21.011,17.19C20.931,16.97 20.581,16.81 20.431,16.52C20.322,16.3 20.132,16.09 19.982,15.82C19.851,15.6 19.851,15.28 19.701,15.02C19.501,14.67 19.521,14.66 19.312,14.31C19.101,13.96 18.761,14.16 18.552,13.81C18.341,13.46 18.701,13.26 18.501,12.91C18.302,12.56 18.351,12.53 18.152,12.18C17.951,11.83 17.751,11.94 17.552,11.59C17.351,11.24 17.242,11.3 17.042,10.95C16.841,10.6 16.861,10.59 16.662,10.24C16.462,9.89 16.462,9.89 16.261,9.54C16.062,9.19 16.281,9.06 16.081,8.71C15.882,8.36 15.651,8.49 15.451,8.14C15.252,7.79 15.601,7.58 15.401,7.23C15.201,6.88 15.151,6.9 14.951,6.55C14.802,6.29 14.571,6.1 14.441,5.88C14.281,5.61 13.872,5.55 13.741,5.34C13.571,5.07 13.741,4.6 13.592,4.42C13.382,4.17 13.071,4.02 12.851,3.92C12.592,3.8 12.262,3.99 11.991,3.99C11.722,3.99 11.542,4.15 11.281,4.26C11.061,4.36 10.672,4.22 10.451,4.48C10.302,4.66 10.292,4.99 10.111,5.26C9.982,5.47 9.702,5.62 9.552,5.89C9.422,6.11 9.242,6.32 9.082,6.58C8.882,6.93 9.012,7 8.802,7.35C8.592,7.7 8.852,7.84 8.642,8.19C8.432,8.54 8.132,8.36 7.932,8.71C7.732,9.06 7.662,9.02 7.462,9.37C7.262,9.72 7.162,9.66 6.962,10.01C6.762,10.36 7.042,10.52 6.842,10.87C6.642,11.22 6.712,11.26 6.512,11.61C6.312,11.96 6.392,12.01 6.192,12.35C5.992,12.69 5.842,12.62 5.642,12.97C5.442,13.32 5.242,13.2 5.032,13.56C4.822,13.92 4.812,13.93 4.692,14.32C4.562,14.74 4.792,14.83 4.592,15.18L4.622,15.21Z"
+        android:strokeWidth="2"
+        android:strokeColor="#FF6868"
+        android:strokeLineCap="round"
+        android:strokeLineJoin="round" />
-
-    <path
-        android:fillColor="#00000000"
-        android:pathData="M4.622,15.21C4.472,15.47 4.332,15.71 4.202,15.93C4.052,16.2 3.632,16.28 3.512,16.5C3.362,16.79 3.132,17 3.052,17.22C2.942,17.53 2.892,17.87 2.912,18.11C2.942,18.39 3.002,18.76 3.142,19C3.282,19.24 3.612,19.41 3.842,19.58C4.032,19.72 4.372,19.55 4.702,19.61C4.932,19.65 5.172,19.78 5.492,19.79C5.742,19.8 6.012,19.8 6.312,19.8C6.562,19.8 6.842,19.63 7.142,19.63C7.542,19.63 7.542,19.79 7.942,19.79C8.342,19.79 8.342,19.88 8.752,19.88C9.162,19.88 9.152,20.12 9.562,20.12C9.972,20.12 9.962,20.12 10.372,20.12C10.781,20.12 10.771,19.79 11.182,19.79C11.592,19.79 11.582,19.9 11.991,19.9C12.401,19.9 12.392,19.99 12.802,19.99C13.212,19.99 13.201,20.09 13.611,20.09C14.021,20.09 14.012,19.74 14.422,19.74C14.832,19.74 14.832,20.03 15.231,20.03C15.632,20.03 15.642,20.04 16.042,20.04C16.441,20.04 16.451,19.77 16.851,19.77C17.152,19.77 17.431,19.6 17.681,19.59C17.992,19.59 18.271,19.87 18.511,19.85C18.831,19.84 19.111,19.85 19.341,19.81C19.671,19.75 19.751,19.41 19.941,19.27C20.171,19.1 20.601,19.16 20.742,18.92C20.882,18.68 21.031,18.38 21.062,18.1C21.091,17.86 21.132,17.5 21.011,17.19C20.931,16.97 20.581,16.81 20.431,16.52C20.322,16.3 20.132,16.09 19.982,15.82C19.851,15.6 19.851,15.28 19.701,15.02C19.501,14.67 19.521,14.66 19.312,14.31C19.101,13.96 18.761,14.16 18.552,13.81C18.341,13.46 18.701,13.26 18.501,12.91C18.302,12.56 18.351,12.53 18.152,12.18C17.951,11.83 17.751,11.94 17.552,11.59C17.351,11.24 17.242,11.3 17.042,10.95C16.841,10.6 16.861,10.59 16.662,10.24C16.462,9.89 16.462,9.89 16.261,9.54C16.062,9.19 16.281,9.06 16.081,8.71C15.882,8.36 15.651,8.49 15.451,8.14C15.252,7.79 15.601,7.58 15.401,7.23C15.201,6.88 15.151,6.9 14.951,6.55C14.802,6.29 14.571,6.1 14.441,5.88C14.281,5.61 13.872,5.55 13.741,5.34C13.571,5.07 13.741,4.6 13.592,4.42C13.382,4.17 13.071,4.02 12.851,3.92C12.592,3.8 12.262,3.99 11.991,3.99C11.722,3.99 11.542,4.15 11.281,4.26C11.061,4.36 10.672,4.22 10.451,4.48C10.302,4.66 10.292,4.99 10.111,5.26C9.982,5.47 9.702,5.62 9.552,5.89C9.422,6.11 9.242,6.32 9.082,6.58C8.882,6.93 9.012,7 8.802,7.35C8.592,7.7 8.852,7.84 8.642,8.19C8.432,8.54 8.132,8.36 7.932,8.71C7.732,9.06 7.662,9.02 7.462,9.37C7.262,9.72 7.162,9.66 6.962,10.01C6.762,10.36 7.042,10.52 6.842,10.87C6.642,11.22 6.712,11.26 6.512,11.61C6.312,11.96 6.392,12.01 6.192,12.35C5.992,12.69 5.842,12.62 5.642,12.97C5.442,13.32 5.242,13.2 5.032,13.56C4.822,13.92 4.812,13.93 4.692,14.32C4.562,14.74 4.792,14.83 4.592,15.18L4.622,15.21Z"
-        android:strokeWidth="2"
-        android:strokeColor="#FF6868"
-        android:strokeLineCap="round"
-        android:strokeLineJoin="round" />

24-32: 중앙 하이라이트 이중 렌더링 가능성 확인

Line 24-29의 스트로크 기반 작은 디테일과 Line 31-32의 흰색 채움 원이 시각적으로 같은 포인트(중앙 점)를 중복 표현할 수 있습니다. 의도된 레이어링이 아니라면 한쪽만 남겨 간소화하세요.

단순화 예시(중앙 점은 채움 원만 유지):

-    <path
-        android:fillColor="#00000000"
-        android:pathData="M11.932,16.01C11.932,16.01 11.972,15.81 11.932,15.84C11.892,15.87 12.162,15.84 12.132,15.8C12.102,15.76 12.012,15.77 11.962,15.77C11.882,15.77 11.892,15.97 11.932,16.01Z"
-        android:strokeWidth="2"
-        android:strokeColor="#ffffff"
-        android:strokeLineCap="round"
-        android:strokeLineJoin="round" />

필요 시 반대로 채움 원을 제거하고 스트로크 디테일만 남기는 선택도 가능합니다(디자인 가이드에 맞춰 결정).

presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListIntent.kt (1)

18-18: 실패 케이스 Intent/SideEffect도 함께 정의해 두는 것을 고려해 주세요

네트워크/서버 오류 등 삭제 실패 시 사용자 피드백(토스트/스낵바)과 바텀시트 유지/복구 정책이 필요할 수 있습니다. 현재 성공 케이스만 있으므로 실패 케이스도 의도적으로 모델링하면 추후 확장성이 좋아집니다. 예: OnFailedDeletedRoutine + ShowToast("삭제에 실패했습니다. 잠시 후 다시 시도해 주세요")

필요하시면 ViewModel reduce 분기 및 화면 연결까지 포함해 패치 제안 드리겠습니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListSideEffect.kt (1)

9-9: 토스트 메시지 문자열 직접 전달 대신 리소스 ID 또는 UiText 래퍼로 전환을 추천

현재 String을 직접 전달하면 다국어/문구 교체 시점이 분산되고 테스트가 어려워집니다. 리소스 ID(@stringres) 또는 UiText 같은 래퍼를 사용하면 UI 계층에서 안전하게 resolve할 수 있습니다.

아래와 같이 변경을 제안합니다(후속으로 화면/VM에서 호출부도 함께 업데이트 필요):

-    data class ShowToast(val message: String) : RoutineListSideEffect
+    data class ShowToast(@androidx.annotation.StringRes val messageResId: Int) : RoutineListSideEffect

또는 UiText 패턴을 사용 중이라면:

-    data class ShowToast(val message: String) : RoutineListSideEffect
+    data class ShowToast(val message: UiText) : RoutineListSideEffect
presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt (1)

14-16: 하위 호환용 오버로드 추가 고려

show의 아이콘을 필수로 만드는 방향은 좋으나, 마이그레이션 중엔 하위 호환 오버로드가 있으면 리팩터링 부담이 줄어듭니다. 필요 시 아래 오버로드 추가를 제안합니다.

추가 코드(이 파일 내 적절한 위치에 배치):

// 기본 성공 아이콘으로 위임
fun show(text: String) = show(text, R.drawable.ic_check_circle_orange)
presentation/src/main/java/com/threegap/bitnagil/presentation/home/util/LocalDateExtension.kt (1)

52-58: 예외 범위를 DateTimeParseException으로 한정하고 detekt 경고를 해소합시다

현재 Exception 전체를 삼키고 있어 detekt에서 경고가 납니다. 파싱 실패만 처리하도록 예외를 축소하면 의도도 명확해집니다.

아래처럼 수정을 제안합니다(추가 import 필요: import java.time.format.DateTimeParseException):

 fun String.toShortDateFormat(): String =
     try {
         val date = LocalDate.parse(this)
         date.format(shortDateFormatter)
-    } catch (e: Exception) {
+    } catch (e: java.time.format.DateTimeParseException) {
         this
     }

추가로, 코드 골프를 원하시면 runCatching을 사용할 수도 있습니다(선호 시):

-fun String.toShortDateFormat(): String =
-    try {
-        val date = LocalDate.parse(this)
-        date.format(shortDateFormatter)
-    } catch (e: Exception) {
-        this
-    }
+fun String.toShortDateFormat(): String =
+    runCatching { LocalDate.parse(this).format(shortDateFormatter) }
+        .getOrElse { this }
presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineUiModel.kt (2)

12-12: 날짜 포맷 유틸 의존성 경로 점검 — 공용 유틸로 승격 고려

presentation/home/util 에 있는 확장함수를 routinelist에서 직접 참조하는 구조는 기능 간 결합을 높입니다. 공용 모듈/패키지(presentation/common/util 등)로 이동해 재사용성을 높이는 것을 권장합니다.


22-30: 기간/삭제여부 필드 및 formattedDateRange 도입은 적절 — 동일 시작/종료일 표기 간소화 제안

현재 동일한 시작/종료일에도 "A - A" 형태로 노출됩니다. 단일 일자일 때는 하이픈 없이 단일 날짜만 표시하면 가독성이 좋습니다.

아래처럼 getter를 보완하는 것을 제안합니다.

-    val formattedDateRange: String
-        get() = "${startDate.toShortDateFormat()} - ${endDate.toShortDateFormat()}"
+    val formattedDateRange: String
+        get() = if (startDate == endDate) {
+            startDate.toShortDateFormat()
+        } else {
+            "${startDate.toShortDateFormat()} - ${endDate.toShortDateFormat()}"
+        }
presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListViewModel.kt (2)

142-144: 삭제 성공 후 재조회(Pessimistic Update) 플로우 적절 — 중복 제거와 널 안전성 개선 제안

두 삭제 메서드의 onSuccess 블록이 동일합니다. 공통 헬퍼로 추출하면 중복이 줄고, 유지보수가 쉬워집니다. 또한 selectedRoutine 접근에 ‘!!’ 대신 안전 접근으로 NPE를 방지해 주세요(호출 경로가 보장되더라도 디펜시브 코딩 추천).

공통 처리 헬퍼 추가(메서드 외부에 추가):

private fun onDeleteSuccess() {
    fetchRoutines()
    sendIntent(RoutineListIntent.OnSuccessDeletedRoutine)
}

각 onSuccess 블록 치환:

-                onSuccess = {
-                    fetchRoutines()
-                    sendIntent(RoutineListIntent.OnSuccessDeletedRoutine)
-                },
+                onSuccess = { onDeleteSuccess() },

널 안전성 개선(예시: 기존 함수 바디 대체 참고):

fun deleteRoutineCompletely() {
    sendIntent(RoutineListIntent.UpdateLoading(true))
    val selected = stateFlow.value.selectedRoutine ?: return
    viewModelScope.launch {
        deleteRoutineUseCase(selected.routineId).fold(
            onSuccess = { onDeleteSuccess() },
            onFailure = {
                Log.e("RoutineListViewModel", "루틴 삭제 실패: ${it.message}")
                sendIntent(RoutineListIntent.UpdateLoading(false))
            },
        )
    }
}

Also applies to: 159-161


105-111: 선택된 루틴 초기화 권장 및 토스트 아이콘 매핑 확인

삭제 완료 후에도 state.selectedRoutine이 남아 있어 이후 액션에서 참조 혼동이 발생할 수 있으므로, 삭제 성공 처리 시 selectedRoutine을 null로 초기화할 것을 권장합니다.
토스트 아이콘은 ShowToastGlobalBitnagilToast.showCheck(...) 매핑을 통해 체크 아이콘이 올바르게 전달되고 있어 별도 수정이 필요 없습니다.

수정 위치
• presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListViewModel.kt
– OnSuccessDeletedRoutine 처리 블록

제안하는 변경 사항

             is RoutineListIntent.OnSuccessDeletedRoutine -> {
-                sendSideEffect(RoutineListSideEffect.ShowToast("삭제가 완료되었습니다."))
-                state.copy(
-                    isLoading = false,
-                    deleteConfirmBottomSheetVisible = false,
-                )
+                sendSideEffect(RoutineListSideEffect.ShowToast("삭제가 완료되었습니다."))
+                state.copy(
+                    isLoading = false,
+                    deleteConfirmBottomSheetVisible = false,
+                    selectedRoutine = null,
+                )
             }

선택 사항

  • 필요 시 ShowToast 사이드이펙트에 icon 정보를 포함하도록 확장할 수 있습니다.
presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/component/template/RoutineDetailsCard.kt (1)

78-85: 요구사항 “비활성화” vs 현재 “숨김 처리” 불일치 — 레이아웃 점프 방지를 위해 disabled 적용 권장

PR 설명대로라면 삭제된 루틴은 “수정 비활성화”가 정확합니다. 현재는 아이콘 자체를 숨겨 레이아웃이 변합니다. 항상 아이콘을 렌더링하되 enabled=false로 비활성화하면 시맨틱과 UX가 모두 맞습니다.

아래처럼 변경 제안합니다.

-            if (!routine.routineDeletedYn) {
-                BitnagilIconButton(
-                    id = R.drawable.ic_edit,
-                    onClick = onEditClick,
-                    tint = null,
-                    paddingValues = PaddingValues(12.dp),
-                )
-            }
+            BitnagilIconButton(
+                id = R.drawable.ic_edit,
+                onClick = onEditClick,
+                enabled = !routine.routineDeletedYn,
+                tint = null,
+                paddingValues = PaddingValues(12.dp),
+            )
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt (2)

39-50: 레이아웃 변경(풀폭 + coolGray30 배경) — 대비(contrast) 재확인 권장

배경이 밝은 회색(coolGray30)인데 텍스트가 흰색입니다. 대비가 낮아질 수 있어 가독성이 떨어질 우려가 있습니다. 디자인 가이드를 재확인해 주세요. 필요하면 텍스트 컬러를 더 어두운 톤으로 변경하는 방안을 고려해주세요.

예:

  • BitnagilTheme.colors.coolGray10 사용,
  • 또는 배경을 더 짙은 톤으로.

117-120: 타입 일관성: shouldPreventDuplicateShow의 icon 파라미터는 이제 비널(Int)이어야 합니다

공개 API가 Int로 바뀐 만큼 내부 비교 함수도 Int로 맞추면 가독성과 타입 일관성이 높아집니다.

-    private fun shouldPreventDuplicateShow(text: String, icon: Int?): Boolean {
+    private fun shouldPreventDuplicateShow(text: String, icon: Int): Boolean {
         val currentTime = System.currentTimeMillis()
         return _text == text && _icon == icon && currentTime - _lastShowTime < 500L
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b86184d and 95c5283.

📒 Files selected for processing (16)
  • app/src/main/java/com/threegap/bitnagil/MainActivity.kt (2 hunks)
  • app/src/main/java/com/threegap/bitnagil/MainNavigator.kt (1 hunks)
  • core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt (5 hunks)
  • core/designsystem/src/main/res/drawable/ic_warning.xml (1 hunks)
  • domain/src/main/java/com/threegap/bitnagil/domain/routine/model/DayOfWeek.kt (1 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt (1 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt (0 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt (0 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeSideEffect.kt (0 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/home/util/LocalDateExtension.kt (2 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListScreen.kt (2 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListViewModel.kt (4 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/component/template/RoutineDetailsCard.kt (6 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListIntent.kt (1 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListSideEffect.kt (1 hunks)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineUiModel.kt (3 hunks)
💤 Files with no reviewable changes (3)
  • presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeViewModel.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt
  • presentation/src/main/java/com/threegap/bitnagil/presentation/home/model/HomeSideEffect.kt
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-23T13:32:26.263Z
Learnt from: l5x5l
PR: YAPP-Github/Bitnagil-Android#41
File: presentation/src/main/java/com/threegap/bitnagil/presentation/mypage/model/MyPageIntent.kt:6-6
Timestamp: 2025-07-23T13:32:26.263Z
Learning: In the Bitnagil Android project's MVI architecture, Intent classes like `LoadMyPageSuccess` are named to represent successful API response results that carry loaded data, not just user actions. This naming convention is used for future API integration where the intent will be triggered when my page data loading succeeds from the server.

Applied to files:

  • presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListIntent.kt
🧬 Code Graph Analysis (4)
presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt (1)
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt (1)
  • show (106-111)
presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListViewModel.kt (2)
presentation/src/main/java/com/threegap/bitnagil/presentation/common/mviviewmodel/MviViewModel.kt (2)
  • sendSideEffect (23-23)
  • sendIntent (30-37)
data/src/main/java/com/threegap/bitnagil/data/routine/service/RoutineService.kt (2)
  • fetchRoutines (14-40)
  • fetchRoutines (15-19)
presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/component/template/RoutineDetailsCard.kt (1)
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilIcon.kt (1)
  • BitnagilIconButton (35-58)
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt (1)
core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilIcon.kt (1)
  • BitnagilIcon (21-33)
🪛 detekt (1.23.8)
presentation/src/main/java/com/threegap/bitnagil/presentation/home/util/LocalDateExtension.kt

[warning] 56-56: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

🔇 Additional comments (21)
domain/src/main/java/com/threegap/bitnagil/domain/routine/model/DayOfWeek.kt (2)

39-41: 로직 유지(LGTM): 요일 정렬 및 한국어 축약 포맷은 그대로입니다.

정렬(ordinal 기준) 후 "월, 화, …"로 조인하는 기존 포맷 로직은 변함없고 문제 없습니다.


38-38: UI/접근성: 빈 리스트 반환 시 "x" 검토 필요

  • 호출 위치
    • presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/component/template/RoutineDetailsCard.kt:135
      (text = "반복: ${routine.repeatDay.formatRepeatDays()}")
  • 검색 결과
    • "x" 문자열은 domain/src/main/java/com/threegap/bitnagil/domain/routine/model/DayOfWeek.kt:38 에서만 사용
    • "반복 없음" 참조는 코드베이스에 존재하지 않음
  • 확인해야 할 사항
    1. 디자인 명세/기획 의도에 따라 빈 리스트 표시가 "x"로 올바른지
    2. 스크린리더 내레이션이 의도대로 동작하는지 (필요 시 Presentation 레이어에서 대체 텍스트 제공)
    3. UI 테스트/스냅샷에서 회귀 여부 (스냅샷 테스트가 있다면 "반복: x" 케이스 추가)
  • 추가 권장
    • 도메인 단위 테스트: 빈 리스트 → "x" 반환 케이스 추가

위 검증 후 이상 없으면 승인 부탁드립니다.

app/src/main/java/com/threegap/bitnagil/MainNavigator.kt (1)

4-9: 타입 세이프 내비게이션 사용을 위한 Navigation Compose 버전 확인 필요

NavDestination.hasRoute<T>()currentBackStackEntryAsState() 조합은 Navigation Compose 2.7.0+ 이상에서만 지원됩니다. 프로젝트에서 사용 중인 androidx.navigation:navigation-compose 버전을 확인해 주세요.

  • Gradle 파일(build.gradle, build.gradle.kts) 또는 버전 카탈로그(libs.versions.toml)에서
    androidx.navigation:navigation-compose 버전 선언 위치를 직접 검토
    스크립트 실행 결과 해당 의존성을 찾지 못했습니다. 의존성 선언 위치를 수동으로 확인해 주세요.
app/src/main/java/com/threegap/bitnagil/MainActivity.kt (1)

12-12: navigationBarsPadding import 추가 적절합니다.

엣지-투-엣지 대응을 위해 시스템 내비게이션 바 패딩을 적용하려는 의도와 일치합니다.

core/designsystem/src/main/res/drawable/ic_warning.xml (3)

16-22: 화이트 스트로크 디테일로 가독성 향상된 점 좋습니다

라운드 캡/조인을 활용한 내부 스트로크는 작은 사이즈(24dp)에서도 인지성을 높여줍니다. 토스트 아이콘으로 사용 시 대비가 충분한 배경(다크 토스트)에서 특히 효과적일 것으로 보입니다.


1-5: 벡터 스케일/테마 컨텍스트에서의 보이기 검토 요청

  • 이 아이콘이 라이트 배경(예: 라이트 테마 토스트 또는 카드 위)에서도 충분한 대비를 가지는지 확인이 필요합니다. 내부 하이라이트가 흰색이므로 라이트 배경에서는 디테일이 소실될 수 있습니다. 필요하면 onWarning에 다크 테마/라이트 테마별 다른 값 또는 알파를 고려해 주세요.
  • 앱이 벡터 스트로크를 사용하는 minSdk/렌더링 파이프라인에서 문제 없는지(특히 지원 라이브러리 사용 여부) 한 번만 확인 부탁드립니다.

7-7: 컬러 리소스(ds_warning, ds_on_warning) 정의 여부 수동 확인 필요

다음 사항을 확인해 주세요:

  • core/designsystem 모듈의 values/colors.xml 파일에 ds_warning, ds_on_warning 컬러 리소스가 정의되어 있는지
  • 정의되어 있지 않다면 해당 리소스를 추가한 후, 아이콘 XML의 하드코딩 색상(#FF6868, #ffffff)을 리소스 참조로 교체 권장

예시 치환안:

-        android:fillColor="#FF6868"
+        android:fillColor="@color/ds_warning"
-        android:strokeColor="#FF6868"
+        android:strokeColor="@color/ds_warning"
-        android:strokeColor="#ffffff"
+        android:strokeColor="@color/ds_on_warning"
-        android:fillColor="#ffffff"
+        android:fillColor="@color/ds_on_warning"
presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineListIntent.kt (1)

18-18: 삭제 성공 Intent 추가 방향 적절합니다

삭제 완료 후 상태 복구(loading 해제, 바텀시트 닫기)와 토스트 트리거를 분리해 의도를 명확히 했네요. 기존 프로젝트의 MVI 네이밍 컨벤션(성공 결과를 나타내는 Intent)과도 잘 맞습니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListScreen.kt (1)

48-51: SideEffect 처리 흐름 깔끔합니다

ShowToast를 화면 컨테이너에서 GlobalBitnagilToast로 위임하는 구성은 MVI에서 일회성 이벤트 처리 패턴에 부합합니다. NavigateToAddRoutine 단일 라인 처리로 일관성도 좋아졌습니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/common/toast/GlobalBitnagilToast.kt (2)

14-16: GlobalBitnagilToast.show 단일 인자 호출 잔존 없음 확인

전역 검색 결과, GlobalBitnagilToast.show(text) 형태의 구 시그니처 호출부가 더 이상 존재하지 않음을 확인했습니다. 해당 변경으로 인한 컴파일 에러 발생 위험이 없습니다.


18-21: 리소스 존재 확인 완료: ic_check_circle_orange
core/designsystem/src/main/res/drawable/ic_check_circle_orange.xml 경로에 아이콘 리소스가 존재함이 확인되었습니다. 빌드/런타임 오류 우려가 없습니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/home/util/LocalDateExtension.kt (1)

14-14: 짧은 날짜 포맷 추가 좋습니다

숫자 기반 포맷이라 Locale 비의존적이며, UI 요구사항(yy.MM.dd)에 맞습니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/model/RoutineUiModel.kt (1)

39-42: Domain → UI 매핑 확장 반영 완료

startDate/endDate/routineDeletedYn 매핑 누락 없이 잘 반영되었습니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListViewModel.kt (1)

74-77: 루틴 등록 네비게이션 사이드이펙트 전송 — OK

등록 진입 동작을 인텐트에서 사이드이펙트로 분리한 방향성 좋습니다.

presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/component/template/RoutineDetailsCard.kt (3)

37-43: infoTextStyle 도입으로 텍스트 스타일 중복 제거 — 좋습니다

여러 텍스트에 동일 스타일을 적용하는 패턴 정리로 유지보수성이 올라갑니다.


134-148: formattedDateRange 사용으로 기간 표기 간소화 — OK

기간/반복/시간 섹션에서 infoTextStyle을 일관 적용한 점도 좋습니다.


163-166: 프리뷰 데이터 확장(기간/삭제여부) — OK

새 필드들이 프리뷰에도 반영되어 스토리 확인이 수월합니다.

core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/atom/BitnagilToastMessage.kt (4)

57-62: 텍스트 스타일/정렬 — OK

바디2 쓰기와 가운데 정렬은 변경된 레이아웃과 잘 어울립니다.


96-103: 토스트 상태에서 아이콘을 비널형(Int)으로 전환 — 일관성 좋아졌습니다

상태/표시 컴포넌트가 아이콘을 항상 요구하도록 정렬된 점 좋습니다.

Also applies to: 106-112


137-140: 프리뷰 갱신 — OK

새로운 API(아이콘 필수)에 맞춰 프리뷰도 정리되어 있습니다.


35-38: 토스트 아이콘 필수화 영향 범위 점검 완료 — 문제없음

  • GlobalBitnagilToast.showCheck/showWarning 래퍼에서
    R.drawable.ic_check_circle_orange, R.drawable.ic_warning 아이콘을 기본 주입
  • 외부 코드(예: RoutineListScreen, HomeNavHost)에서는 모두 해당 래퍼를 사용
  • BitnagilToastMessage를 직접 호출하는 위치가 없어 아이콘 파라미터 필수화에 따른 컴파일 오류 없음

필요 시 추가 상태별 래퍼(showError, showInfo 등)만 별도 구현을 검토해주세요.

Copy link
Copy Markdown
Contributor

@l5x5l l5x5l left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다! 머지 진행하시죠!

@wjdrjs00 wjdrjs00 merged commit 63deaf0 into develop Aug 20, 2025
2 checks passed
@wjdrjs00 wjdrjs00 deleted the feature/#114-routine-list branch August 22, 2025 01:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능 구현 🧤 대현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] 루틴 리스트 화면 미구현 기능을 구현합니다.

2 participants